package com.xuyuan.remote;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Cache;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.http.client.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.io.File;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
public class RestTemplateExample {

    private final String URL = "${ip}:${port}/context/path";
    private RestTemplate restTemplate = new RestTemplate();

    public static void main(String[] args) {
        String url = UriComponentsBuilder.fromHttpUrl("http://exmaple.com/context/path").queryParam("paramVar1", "param1").queryParam("paramVar12", "param2").toUriString();
        String result = "http://exmaple.com/context/path?paramVar1=param1&paramVar12=param2";
        System.out.println(url.equals(result));

        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://exmaple.com/context/path").pathSegment("pathVar1", "pathVar2", "pathVar3");
        // builder.replacePath("pathVar1");
        System.out.println(builder.build().toUriString());

        String url3 = UriComponentsBuilder.newInstance().scheme("http").host("exmaple.com").port(80).path("/context/path").queryParam("paramVar1", "param1").queryParam("paramVar2", "param2").queryParam("paramVar3", "param3").build().toUriString();
        log.info(url3);

    }

    /**
     * HttpURLConnection创建定制化的RestTemplate
     */
    @Bean("httpURLConnectionRestTemplate")
    public RestTemplate customRestTemmplateConfig1() {
        SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
        simpleClientHttpRequestFactory.setConnectTimeout(3000);
        simpleClientHttpRequestFactory.setReadTimeout(3000);
        RestTemplate restTemplate1 = new RestTemplate(simpleClientHttpRequestFactory);
        restTemplate.getMessageConverters().add(null); // 添加自定义的报文序列化转换器
        List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
        interceptors.add((request, body, execution) -> {

            log.info("请求前处理");
            ClientHttpResponse response = execution.execute(request, body);
            log.info("请求后处理");
            return response;
        });// 拦截责任链添加自定义拦截逻辑
        return restTemplate1;
    }

    /**
     * HttpClient创建定制化的RestTemplate
     */
    // @Bean("httpClientRestTemplate")
    // public RestTemplate customRestTemmplateConfig2() {
    //     Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
    //             .register("http", PlainConnectionSocketFactory.getSocketFactory())
    //             .register("https", SSLConnectionSocketFactory.getSocketFactory()).build();
    //
    //     PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
    //     connectionManager.setMaxTotal(100);
    //     connectionManager.setDefaultMaxPerRoute(20);
    //     connectionManager.setValidateAfterInactivity(100000);
    //
    //     RequestConfig customRequestConfig = RequestConfig.custom().setConnectionRequestTimeout(3000).setSocketTimeout(3000).setConnectTimeout(1000).build();
    //
    //     CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(customRequestConfig).setConnectionManager(connectionManager).build();
    //
    //     ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(client);
    //     return new RestTemplate(requestFactory);
    // }

    /**
     * OkHttp创建定制化的RestTemplate
     */
    @Bean("okHttpRestTemplate")
    public RestTemplate customRestTemmplateConfig3() {
        OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout(3, TimeUnit.SECONDS) // 读超时时间
                .writeTimeout(3, TimeUnit.SECONDS) // 写超时时间
                .connectTimeout(1, TimeUnit.SECONDS) // 连接超时时间
                .callTimeout(5, TimeUnit.SECONDS) // 响应超时时间
                .addInterceptor(new OKHttpExample.CustomInterceptor()) // 自定义拦截器
                .cache(new Cache(new File(""), 1024 * 1024 * 100)) // 自定义缓存，CacheInterceptor会使用
                .cookieJar(new OKHttpExample.CustomCookieJar()) // 自定义Cookie，BridgeInterceptor会使用
                .followRedirects(true) // 支持RetryAndFollowUpInterceptor的重定向
                .followSslRedirects(true) // 支持SSL重定向
                .retryOnConnectionFailure(true) // 支持RetryAndFollowUpInterceptor的重试
                .connectionPool(new ConnectionPool(10, 600, TimeUnit.SECONDS)).build();

        ClientHttpRequestFactory okHttp3ClientHttpRequestFactory = new OkHttp3ClientHttpRequestFactory(okHttpClient);
        return new RestTemplate(okHttp3ClientHttpRequestFactory);
    }

    /**
     * GET请求：1 - 不带参数的GET请求
     */
    public void testGet1() {
        String baseUrl = "http://exmaple.com/context/path";
        String result = restTemplate.getForObject(baseUrl, String.class);
        log.info(result);

        ResponseEntity<String> responseHttpEntity = restTemplate.getForEntity(baseUrl, String.class);
        log.info(responseHttpEntity.getBody());

        ResponseEntity<String> responseHttpEntity1 = restTemplate.exchange(baseUrl, HttpMethod.GET, new HttpEntity<Void>((Void) null), String.class);
        log.info(responseHttpEntity.getBody());
    }

    /**
     * GET请求：2- 带路径参数的GET请求
     */
    public void testGet2() {
        String url1 = UriComponentsBuilder.fromHttpUrl("http://exmaple.com/context/path").pathSegment("pathVar1", "pathVar2", "pathVar3").build().toUriString();
        String forObject = restTemplate.getForObject(url1, String.class);
        log.info(forObject);

        String url2 = "http://exmaple.com/context/path";
        ResponseEntity<String> responseHttpEntity = restTemplate.getForEntity(url2, String.class, "pathVar1", "pathVar2", "pathVar3");
        log.info(responseHttpEntity.getBody());

        String url3 = UriComponentsBuilder.newInstance().scheme("http").host("exmaple.com").port(80).path("/context/path").pathSegment("pathVar1", "pathVar2", "pathVar3").build().toUriString();
        ResponseEntity<String> responseHttpEntity1 = restTemplate.exchange(url3, HttpMethod.GET, new HttpEntity<Void>((Void) null), String.class);
        log.info(responseHttpEntity.getBody());
    }

    /**
     * GET请求：3- 带请求参数的GET请求
     */
    public void testGet3() {
        String url1 = UriComponentsBuilder.fromHttpUrl("http://exmaple.com/context/path").queryParam("paramVar1", "param1").queryParam("paramVar2", "param2").queryParam("paramVar3", "param3").build().toUriString();
        String forObject = restTemplate.getForObject(url1, String.class);
        log.info(forObject);

        String url2 = "http://exmaple.com/context/path?paramVar1=param1&paramVar2=param2&paramVar3=param3";
        ResponseEntity<String> responseHttpEntity = restTemplate.getForEntity(url2, String.class);
        log.info(responseHttpEntity.getBody());

        String url3 = UriComponentsBuilder.newInstance().scheme("http").host("exmaple.com").port(80).path("/context/path").queryParam("paramVar1", "param1").queryParam("paramVar2", "param2").queryParam("paramVar3", "param3").build().toUriString();
        ResponseEntity<String> responseHttpEntity1 = restTemplate.exchange(url3, HttpMethod.GET, new HttpEntity<Void>((Void) null), String.class);
        log.info(responseHttpEntity.getBody());
    }

    /**
     * POST请求: 1-复杂对象/字符串
     */
    public void testPost() {
        String url = "http://exmaple.com/context/path";

        HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "application/json");

        CustomRequestBody requestBody = new CustomRequestBody("xuyuan", 25);

        HttpEntity<CustomRequestBody> requestEntity = new HttpEntity<>(requestBody, headers);

        String result = restTemplate.postForObject(url, requestEntity, String.class);
        log.info(result);

        ResponseEntity<String> responseHttpEntity1 = restTemplate.postForEntity(url, requestEntity, String.class);
        log.info(responseHttpEntity1.getBody());

        ResponseEntity<String> responseHttpEntity2 = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
        log.info(responseHttpEntity2.getBody());
    }

    /**
     * POST请求: 2-表单
     */
    public void testPost2() {
        String url = "http://exmaple.com/context/path";

        HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "application/json");

        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("name", "xuyuan");
        map.add("age", "25");

        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(map, headers);

        String result = restTemplate.postForObject(url, requestEntity, String.class);
        log.info(result);

        ResponseEntity<String> responseHttpEntity1 = restTemplate.postForEntity(url, requestEntity, String.class);
        log.info(responseHttpEntity1.getBody());

        ResponseEntity<String> responseHttpEntity2 = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
        log.info(responseHttpEntity2.getBody());
    }

    /**
     * POST请求: 3-文件上传
     */
    public void testPost3() {
        String url = "http://exmaple.com/context/path";

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        File file = new File("/upload/file.txt");
        Resource resource = new FileSystemResource(file);
        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        map.add("file", resource);

        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);

        String result = restTemplate.postForObject(url, requestEntity, String.class);
        log.info(result);

        ResponseEntity<String> responseHttpEntity1 = restTemplate.postForEntity(url, requestEntity, String.class);
        log.info(responseHttpEntity1.getBody());

        ResponseEntity<String> responseHttpEntity2 = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
        log.info(responseHttpEntity2.getBody());
    }

    /**
     * 添加报文头 HttpHeaders
     */
    public void addHeader() {

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("Accept", "application/json");
        headers.add("Accept-Encoding", "gzip, deflate");
        headers.add("Accept-Language", "zh-CN,zh;q=0.9");
        headers.add("Connection", "keep-alive");

        HttpEntity<String> requestHttpEntity = new HttpEntity<>("test", headers);
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class CustomRequestBody {
        private String name;
        private int age;
    }
}
